/**
* \file		Entrepot.c
* \brief	Code des fonctions du module Entrepot
* \details	C'est ici qu'est le code des accesseurs, mutateurs ainsi que
*		la fonction de test vérifant le bon fonctionnement du module
*		Entrepot.
*		Une description de la structure Entrepot est fournie à
*		la rubrique \link Entrepot.h
*/

/* voir si on garde tous les includes */
#include "Entrepot.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

/*========================== Gestion de la mémoire ==========================*/

void initRessourcesEntr(Entrepot *pstock)
{
   pstock->bois = 0;
   pstock->metal = 0;
   pstock->houblon = 0;
   pstock->nourriture = 0;
   pstock->biere = 0;
   pstock->modifProduction = 0;
}

void creerEntr(Entrepot **pnouvEntr)
{
   *pnouvEntr = (Entrepot *)malloc(sizeof(Entrepot));
   initRessourcesEntr(*pnouvEntr);
}

void detruireEntr(Entrepot *pentr)
{
   free(pentr);
}

/*============================= Accesseurs =============================*/

unsigned int getBoisEntr(const Entrepot *pstock)
{
   return pstock->bois;
}

unsigned int getMetalEntr(const Entrepot *pstock)
{
   return pstock->metal;
}

unsigned int getHoublonEntr(const Entrepot *pstock)
{
   return pstock->houblon;
}

unsigned int getNourritureEntr(const Entrepot *pstock)
{
   return pstock->nourriture;
}

unsigned int getBiereEntr(const Entrepot *pstock)
{
   return pstock->biere;
}

int getBonusProd(const Entrepot *pstock)
{
  return pstock->modifProduction;
}

/*============================== Mutateurs ==============================*/

void ajouteBoisEntr(Entrepot *pstock, int quantite)
{
   if ((int)pstock->bois < -quantite)
	{
	   pstock->bois = 0;
	}
   else
	{
	   pstock->bois += quantite;
	}
}

void ajouteMetalEntr(Entrepot *pstock, int quantite)
{
   if ((int)pstock->metal < -quantite)
	{
	   pstock->metal = 0;
	}
   else
	{
	   pstock->metal += quantite;
	}
}

void ajouteHoublonEntr(Entrepot *pstock, int quantite)
{
   if ((int)pstock->houblon < -quantite)
	{
	   pstock->houblon = 0;
	}
   else
	{
	   pstock->houblon += quantite;
	}
}

void ajouteNourritureEntr(Entrepot *pstock, int quantite)
{
   if ((int)pstock->nourriture < -quantite)
	{
	   pstock->nourriture = 0;
	}
   else
	{
	   pstock->nourriture += quantite;
	}
}

void ajouteBiereEntr(Entrepot *pstock, int quantite)
{
   if ((int)pstock->biere < -quantite)
	{
	   pstock->biere = 0;
	}
   else
	{
	   pstock->biere += quantite;
	}
}

void ajouteModifProd(Entrepot *pstock, int modificateur)
{
  pstock->modifProduction += modificateur;
}

/*========================== Fonctions de Test ==========================*/
/**
* \brief	Procédure interne : teste les ajoute et les Get du module
* \param	valIni		Entier, valeur initiale
* \param	valAjoutee	Tableau d'entiers listant les valeurs à
*				ajouter successivement aux différentes
*				ressources de l'entrepôt
* \param	tabpGet		Tableau de pointeurs sur fonction
*				récapitulant les Get à tester
* \param	tabajoute		Tableau de pointeurs sur fonction
*				récapitulant les ajoute à tester
* \param	nbFonc		Nombre de paires ajoute/Get à tester
* \param	nbVar		Nombre de valeurs à ajouter en tout
* \param	stock		Entrepot initialisé
*/
static void verifajouteGetEntr(int valIni,
		 int valAjoutee[],
		 unsigned int (*tabpGet[])(const Entrepot *),
		 void (*tabpajoute[])(Entrepot *, int),
		 int nbFonc,
		 int nbVar,
		 Entrepot stock )
{
   int i, j;
   int quantAttendue = valIni;

   for(i=0; i<nbFonc; i++)
	{
	   for(j=0; j<nbVar ;j++)
		{
		   tabpajoute[i](&stock, valAjoutee[j]);

		   quantAttendue = quantAttendue + valAjoutee[j];

		   if(quantAttendue < 0)
			{
			   quantAttendue = 0;
			}

		   assert(quantAttendue == tabpGet[i](&stock));

		}
	}
}

void testEntrepot()
{
   Entrepot *stock;
   int var[] = {-20, 0, 10, 100, -50, -70};

/* tableau de pointeurs pointant sur les différents Get à tester */
   unsigned int (*tabpGet[])(const Entrepot *) = {getBoisEntr,
					  getMetalEntr,
					  getHoublonEntr,
					  getNourritureEntr,
					  getBiereEntr};

/* tableau de pointeurs pointant sur les différents ajoute à tester */
   void (*tabpajoute[])(Entrepot *, int) = {ajouteBoisEntr,
					 ajouteMetalEntr,
					 ajouteHoublonEntr,
					 ajouteNourritureEntr,
					 ajouteBiereEntr};

   printf("Test de l'Entrepot\n");

   printf("\tInitialisation de l'entrepôt\t\t\t");
   creerEntr(&stock);
   assert(	(stock->bois == 0)&&
		(stock->metal == 0)&&
		(stock->houblon == 0)&&
		(stock->nourriture == 0)&&
		(stock->biere == 0));
   printf("OK\n");

   printf("\tAffectation et récupération de valeurs\t\t");
   verifajouteGetEntr(0, var, tabpGet, tabpajoute, 5, 6, *stock);
   printf("OK\n\n");
   detruireEntr(stock);
}
